package com.itcz.web.controller;

import cn.hutool.core.compress.ZipWriter;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.itcz.maker.meta.Meta;
import com.itcz.maker.template.TemplateMaker;
import com.itcz.maker.template.model.TemplateMakerFileConfig;
import com.itcz.maker.template.model.TemplateMakerModelConfig;
import com.itcz.maker.template.model.TemplateMakerOutputConfig;
import com.itcz.web.common.BaseResponse;
import com.itcz.web.common.ErrorCode;
import com.itcz.web.common.ResultUtils;
import com.itcz.web.exception.BusinessException;
import com.itcz.web.manager.OssManager;
import com.itcz.web.model.dto.template.TemplateMakeRequest;
import com.itcz.web.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.List;
import java.util.concurrent.CompletableFuture;


/**
 * 项目模板接口
 *
 * @author <a href="https://github.com/liyupi">奥数定理</a>
 * @from <a href="https://blog.csdn.net/qq_63143493?spm=1000.2115.3001.5343">个人博客</a>
 */
@RestController
@RequestMapping("/template")
@Slf4j
public class TemplateController {

    // 注入UserService对象
    @Resource
    private UserService userService;

    // 注入OssManager对象
    @Resource
    private OssManager ossManager;

    /**
     * 制作项目模板
     *
     * @param templateMakeRequest 模板制作请求对象
     * @param request Http请求对象
     * @return 返回服务器虚拟路径
     */
    @PostMapping("/make/url")
    public BaseResponse<String> makeTemplate(@RequestBody TemplateMakeRequest templateMakeRequest,
                                              HttpServletRequest request) {
        // 获取前端传入的参数
        Long id = null;
        if(!StrUtil.isBlank(templateMakeRequest.getId())) {
             id= Long.valueOf(templateMakeRequest.getId());
        }
        Meta newMeta = templateMakeRequest.getMeta();
        String originProjectPath = templateMakeRequest.getOriginProjectPath();
        TemplateMakerFileConfig templateMakerFileConfig = templateMakeRequest.getFileConfig();
        TemplateMakerModelConfig templateMakerModelConfig = templateMakeRequest.getModelConfig();
        TemplateMakerOutputConfig templateMakerOutputConfig = templateMakeRequest.getOutputConfig();

        // 由于前端暂时无法传输空字符串（todo)
        if((templateMakerFileConfig.getFiles()) != null) {
            List<TemplateMakerFileConfig.FileInfoConfig> fileInfoConfigList = templateMakerFileConfig.getFiles();
            for (int i = 0; i < fileInfoConfigList.size(); i++) {
                TemplateMakerFileConfig.FileInfoConfig fileInfoConfig = fileInfoConfigList.get(i);
                // 如果文件配置为空对象，说明用户想要无文件过滤和生效条件，路径为""的文件配置
                if(fileInfoConfig == null) {
                    fileInfoConfig = new TemplateMakerFileConfig.FileInfoConfig();
                    fileInfoConfig.setPath("");
                    // 设置对象
                    fileInfoConfigList.set(i, fileInfoConfig);
                    // 如果只是path为空，说明用户想要有文件过滤或者生效条件，路径为""的文件配置
                } else if(fileInfoConfig.getPath() == null) {
                    fileInfoConfig.setPath("");
                }
            }
        }

//        // 如果默认值为“false”或"true"，则转换成boolean类型的false或true(前端已实现）
//        if (templateMakerModelConfig.getModels() != null) {
//            List<TemplateMakerModelConfig.ModelInfoConfig> modelInfoConfigList = templateMakerModelConfig.getModels();
//            for (TemplateMakerModelConfig.ModelInfoConfig modelInfoConfig : modelInfoConfigList) {
//                Object defaultValue = modelInfoConfig.getDefaultValue();
//                // 仅处理字符串类型的默认值
//                if (defaultValue instanceof String) {
//                    String strValue = (String) defaultValue;
//                    // 使用 equalsIgnoreCase 处理大小写，并去除空格
//                    if ("false".equalsIgnoreCase(strValue.trim())) {
//                        modelInfoConfig.setDefaultValue(false);
//                    } else if ("true".equalsIgnoreCase(strValue.trim())) {
//                        modelInfoConfig.setDefaultValue(true);
//                    }
//                }
//            }
//        }

        // 需要登陆
        userService.getLoginUser(request);

        // 1）定义工作空间，用来存放下载的原始项目文件、其他临时文件
        // 没有id则生成id
        if(id == null) {
            id = IdUtil.getSnowflakeNextId();
        }

        // 项目根目录
        String projectDir = System.getProperty("user.dir");
        // 单次制作的工作空间目录
            String templatePath = String.format("%s/.temp/template/make/%s", projectDir, id);
        // 该目录不存在时进行创建多级目录，并将原资源目录复制到该目录下
        if(!FileUtil.exist(templatePath)) {
            FileUtil.mkdir(templatePath);
            // 2）判断原始项目路径是否正确
            if(StrUtil.isBlank(originProjectPath)) {
                // 出现异常，则删除临时文件
                FileUtil.del(templatePath);
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "原始项目路径不存在");
            }

            // 3）从对象存储OSS中下载项目模板文件
            // 原始项目文件的本地路径
            String localZipFilePath = templatePath + "/project.zip";
            // 判断本地路径是否存在
            if(!FileUtil.exist(localZipFilePath)) {
                FileUtil.touch(localZipFilePath);
            }
            // 下载项目模板文件到本地路径
            try {
                ossManager.getObject(originProjectPath, localZipFilePath);
            } catch (Throwable e) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "原始项目文件下载失败");
            }

            // 4）解压文件
            ZipUtil.unzip(localZipFilePath, templatePath + File.separator + "template");
        }

        // 5) 调用制作工具
        try {
            TemplateMaker.makeTemplateByTemplatePath(newMeta,
                    templatePath,
                    templateMakerFileConfig,
                    templateMakerModelConfig,
                    templateMakerOutputConfig,
                    id);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "制作模板失败");
        }

        // 6）压缩生成好的项目模板文件和元数据文件
        String zipFilePath = templatePath + File.separator + "template.zip";
        // 创建ZipWriter对象，实现Zip生成封装
        try (ZipWriter zipWriter = ZipWriter.of(new File(zipFilePath), CharsetUtil.CHARSET_UTF_8)) {
            // 添加meta.json文件
            File metaJsonFile = new File(templatePath, "meta.json");
            // 第二个参数指定ZIP包内路径，直接放在根目录
            zipWriter.add("meta.json", FileUtil.getInputStream(metaJsonFile));

            // 添加template目录
            File templateDir = new File(templatePath, "template");
            // 使用add方法添加目录，withSrcDir=true表示包含父目录
            zipWriter.add(true, null, templateDir);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "压缩失败");
        }

        // 7）生成可访问的URL(服务器虚拟路径）
        String accessUrl = String.format("%s://%s:%d/api/template/%d/template.zip",
                request.getScheme(),
                request.getServerName(),
                request.getServerPort(),
                id);

        // 应使用配置化的域名（示例为开发环境配置）
        // String accessUrl = String.format("%s/template/%d/template.zip",
        // yourConfig.getCdnDomain(), // 从配置读取域名
        // id);

        return ResultUtils.success(accessUrl);
    }


    /**
     * 下载项目模板压缩文件
     *
     * @param request Http请求对象
     * @param response response响应对象
     * @param id id
     * @throws IOException IO异常
     */
    @PostMapping("/make/download")
    public void downloadTemplate(HttpServletRequest request, HttpServletResponse response, String id) throws IOException {
        // 项目根目录
        String projectDir = System.getProperty("user.dir");
        // 项目模板压缩文件路径
        String templatePath = String.format("%s/.temp/template/make/%s", projectDir, id);
        String templateZipFilePath = templatePath + "/template.zip";
        // 需要登陆
        userService.getLoginUser(request);
        try {
            // 下载
            // 设置响应头
            response.setContentType("application/octet-stream;charset=UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=template.zip");
            // 写入响应
            Files.copy(new File(templateZipFilePath).toPath(), response.getOutputStream());
        } catch (IOException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "下载失败");
        }

        // 异步清理临时文件
        CompletableFuture.runAsync(() -> {
            FileUtil.del(templatePath);
        });
    }
}
